﻿namespace YidanSoft.Library.EditorUtility.WinControls
{
    using System;
    using System.ComponentModel;
    using System.Diagnostics;
    using System.Drawing;
    using System.Windows.Forms;
    using YidanSoft.Library.EditorUtility.General;
    using YidanSoft.Library.EditorUtility.Win32;

    [ToolboxItem(false)]
    internal class ArrowButton : Button
    {
        private ColorPicker colorPicker;
        private YidanSoft.Library.EditorUtility.General.DrawState drawState;

        public ArrowButton()
        {
            this.colorPicker = null;
            this.drawState = YidanSoft.Library.EditorUtility.General.DrawState.Normal;
        }

        public ArrowButton(ColorPicker colorPicker)
        {
            this.colorPicker = null;
            this.drawState = YidanSoft.Library.EditorUtility.General.DrawState.Normal;
            base.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque | ControlStyles.UserPaint, true);
            this.colorPicker = colorPicker;
            base.TabStop = false;
        }

        private void DrawArrowState(Graphics g, YidanSoft.Library.EditorUtility.General.DrawState state)
        {
            if (this.colorPicker != null)
            {
                if (!((state != YidanSoft.Library.EditorUtility.General.DrawState.Pressed) || this.colorPicker.colorDropDown.Visible))
                {
                    state = YidanSoft.Library.EditorUtility.General.DrawState.Hot;
                }
                this.DrawBackground(g, state);
                Rectangle clientRectangle = base.ClientRectangle;
                SizeF physicalDimension = base.Image.PhysicalDimension;
                int width = (int) physicalDimension.Width;
                int height = (int) physicalDimension.Height;
                if ((width > clientRectangle.Width) || (height > clientRectangle.Height))
                {
                    Debug.WriteLine("Image dimensions need to be smaller that button's dimension...");
                }
                else
                {
                    int x = (base.Width - width) / 2;
                    int y = (base.Height - height) / 2;
                    this.DrawImage(g, state, base.Image, x, y);
                }
            }
        }

        private void DrawBackground(Graphics g, YidanSoft.Library.EditorUtility.General.DrawState state)
        {
            Rectangle clientRectangle = base.ClientRectangle;
            if ((state == YidanSoft.Library.EditorUtility.General.DrawState.Normal) || (state == YidanSoft.Library.EditorUtility.General.DrawState.Disable))
            {
                g.FillRectangle(new SolidBrush(SystemColors.Control), clientRectangle);
                g.DrawRectangle(Pens.White, clientRectangle.Left, clientRectangle.Top, clientRectangle.Width - 1, clientRectangle.Height - 1);
            }
            else if ((state == YidanSoft.Library.EditorUtility.General.DrawState.Hot) || (state == YidanSoft.Library.EditorUtility.General.DrawState.Pressed))
            {
                if (state == YidanSoft.Library.EditorUtility.General.DrawState.Hot)
                {
                    g.FillRectangle(new SolidBrush(ColorUtil.VSNetSelectionColor), clientRectangle);
                }
                else
                {
                    g.FillRectangle(new SolidBrush(ColorUtil.VSNetPressedColor), clientRectangle);
                }
                g.DrawRectangle(SystemPens.Highlight, clientRectangle.Left, clientRectangle.Top, clientRectangle.Width - 1, clientRectangle.Height - 1);
            }
        }

        private void DrawImage(Graphics g, YidanSoft.Library.EditorUtility.General.DrawState state, Image image, int x, int y)
        {
            SizeF physicalDimension = base.Image.PhysicalDimension;
            int width = (int) physicalDimension.Width;
            int height = (int) physicalDimension.Height;
            if (state == YidanSoft.Library.EditorUtility.General.DrawState.Disable)
            {
                ControlPaint.DrawImageDisabled(g, base.Image, x, y, SystemColors.Control);
            }
            else
            {
                g.DrawImage(base.Image, x, y, width, height);
            }
        }

        protected override void OnGotFocus(EventArgs e)
        {
            base.OnGotFocus(e);
        }

        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);
            if (this.colorPicker != null)
            {
                this.colorPicker.DrawState = YidanSoft.Library.EditorUtility.General.DrawState.Pressed;
            }
        }

        protected override void OnMouseEnter(EventArgs e)
        {
            base.OnMouseEnter(e);
            if (this.colorPicker != null)
            {
                this.colorPicker.DrawState = YidanSoft.Library.EditorUtility.General.DrawState.Hot;
            }
        }

        protected override void OnMouseLeave(EventArgs e)
        {
            base.OnMouseLeave(e);
            if (this.colorPicker != null)
            {
                Point mousePosition = Control.MousePosition;
                if (!(this.colorPicker.ClientRectangle.Contains(this.colorPicker.PointToClient(mousePosition)) || this.colorPicker.colorTextBox.ContainsFocus))
                {
                    this.colorPicker.DrawState = YidanSoft.Library.EditorUtility.General.DrawState.Normal;
                }
            }
        }

        protected override void OnPaint(PaintEventArgs pe)
        {
            base.OnPaint(pe);
            Graphics g = pe.Graphics;
            this.DrawArrowState(g, this.drawState);
        }

        private void RequestMouseLeaveMessage(IntPtr hWnd)
        {
            TRACKMOUSEEVENTS tme = new TRACKMOUSEEVENTS();
            tme.cbSize = 0x10;
            tme.dwFlags = 2;
            tme.hWnd = hWnd;
            tme.dwHoverTime = 0;
            WindowsAPI.TrackMouseEvent(ref tme);
        }

        protected override void WndProc(ref Message m)
        {
            Msg msg = (Msg) m.Msg;
            switch (m.Msg)
            {
                case 0x200:
                    if (this.colorPicker != null)
                    {
                        this.RequestMouseLeaveMessage(m.HWnd);
                        this.colorPicker.DrawState = YidanSoft.Library.EditorUtility.General.DrawState.Hot;
                    }
                    break;

                case 0x2a3:
                {
                    Point mousePosition = Control.MousePosition;
                    if (!(((this.colorPicker == null) || this.colorPicker.ClientRectangle.Contains(this.colorPicker.PointToClient(mousePosition))) || this.colorPicker.colorTextBox.ContainsFocus))
                    {
                        this.colorPicker.DrawState = YidanSoft.Library.EditorUtility.General.DrawState.Normal;
                    }
                    break;
                }
            }
            base.WndProc(ref m);
        }

        internal YidanSoft.Library.EditorUtility.General.DrawState DrawState
        {
            get
            {
                return this.drawState;
            }
            set
            {
                if (this.drawState != value)
                {
                    this.drawState = value;
                    base.Invalidate();
                }
            }
        }
    }
}

